package com.woniuxy.Utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;

/**；这个工具类的三个作用；sign；生成token。verify；校验token.getUsername;通过token反向解析出username
 * @Author：向天浩
 * @Date：2022/2/23 11:44
 * @Description :；我们使用username和password来生成一个唯一的token
 */
public class JwtUtil {
    //创建一个时间戳来设置签名有效时间
    private static final long EXP_Time=5*60*10000;

//    签名生成token
    public static String sign(String username,String password){

        // username 用于签名的往claim放入的信息
        //password  这个可以用来当做 盐 值.如果账号名一样，则通过密码的不同来区分不同用户
        //withExpiresAt有效时间
        Algorithm algorithm = Algorithm.HMAC256(password);//使用算法对密码加密
        return JWT.create().withClaim("username",username)
                .withExpiresAt(new Date(System.currentTimeMillis()+EXP_Time)).sign(algorithm);
    }


    /**
     *功能描述
     *  @: 因为生成token的时候是使用的username和password，所以校验token的时候需要再次使用上次的username和password来生成一个校验器，
     * @:  然后将前端传入的token放入到这个校验器中进行判断这个token是不是使用这个username和password生成的token
     * @Author: 向天浩
     * @Date: 2022/2/23 11:59
     * @param token
     * @param username
     * @param password
     * @return boolean
     */
    public static boolean verify(String token,String username,String password){

        //因为密码是加密过在放入的jwt中，所以对比的时候不能使用原密码进行对比，需要加密后进行对比
        Algorithm algorithm = Algorithm.HMAC256(password);
        //传入你签名时候的秘钥，还有claim属性。你的token在sign是用哪些参数生成的，在里使用相同参数生成，然后和原来的token对比就知道是不是正确的
        //因为我们的token是通过usernam和password来生成的，所以在这使用username和password来生成一个校验器
        JWTVerifier Verifier=JWT.require(algorithm).withClaim("username",username).build();
        //这个方法就是校验jwt正确性的,将传入的token放入这个方法就可以校验token是否匹配
        Verifier.verify(token);
        //直接返回true，因为如果是false会抛异常，程序会停掉
        return true;
    }

        /**
         *功能描述 @:因为我们的token是使用usernam和password来生成的，所以也可以使用这个token反向解析出我们的username
         * 功能描述；@；我们拿到通过token解析出来的username就可以去数据库查询该用户的所有信息，比如他的权限，他的角色，来对他进行相应的授权
         * @Author: 向天浩
         * @Date: 2022/2/23 12:08
         * @param token
         * @return java.lang.String
         */
        public static String getUsername(String token){
        //对这个token进行解码decode(解码的意思),解码后的对象可以获取到数值
       //asString();将此声明作为字符串获取。如果该值不是 String 类型或无  法转换为 String，则返回 null。返回： String 形式的值或 null。
            DecodedJWT decode = JWT.decode(token);
            return decode.getClaim("username").asString();
        }
}
